home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
audio
/
chaterbx
/
part02
/
8svx.c
next >
Wrap
C/C++ Source or Header
|
1990-01-17
|
8KB
|
332 lines
/* quasi-minimal IFF 8SVX sample file loader for Karl's Audio Stuff
* by Karl Lehenbauer, based originally on public domain IFF code from
* Electronic Arts
* rewritten 2/25/88 KEL to support chaining of samples through a
* central sample store and to support music (it's now carrying
* around octave and one-shot info)
*
* this version for the sound effect player has had the octave stuff
* hacked back out but the central sample store is still there
*
*/
#include <exec/types.h>
#include <functions.h>
#include <exec/memory.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <stdio.h>
#include <fcntl.h>
#include "assert.h"
#include "iff.h"
#include "8svx.h"
#include "sample.h"
struct List SampleStore;
struct List *SampleList = &SampleStore;
/* this is a global variable that is set by Load8SVX to indicate whether
* it found the sample in memory already or not. When we're playing
* sounds for the timer and noload is selected, it's a good thing to know
* and we already return a value (bleah, C is a bit restrictive in this
* case)
*/
int sample_was_in_cache;
char *SamplePath = "ChatterBox:";
void UnloadAllSamples()
{
#ifdef DEBUG
fprintf(stderr,"UnloadAllSamples cleanup routine executing\n");
#endif
while (SampleList->lh_TailPred != SampleList)
{
UnloadSampleAt(SampleList->lh_Head);
}
#ifdef DEBUG
fprintf(stderr,"UnloadAllSamples cleanup routine complete\n");
#endif
}
Init8SVX()
{
NewList(SampleList);
add_cleanup(UnloadAllSamples);
}
Sample *Load8SVX(fname)
char *fname;
{
int iffile;
ChunkHeader chunkhead;
Voice8Header voicehead;
LONG samplebytes, fibbytes;
LONG formtype;
char *sampbufp, *fibbufp;
register Sample *samptr;
LONG headsize;
short flags = 0;
char fnamebuf[256];
assert(sizeof(chunkhead) == 8);
#ifndef NOAUDIT
if (SampleList->lh_Head == (struct Node *)NULL)
panic("called Load8SVX without calling Init8SVX\n");
#endif
#ifdef DEBUG
printf("checking sample store for %s - ",fname);
#endif
if ((samptr = (Sample *)FindName(SampleList, fname)) != NULL)
{
#ifdef DEBUG
printf("request for %s satisfied from sample store\n",fname);
#endif
sample_was_in_cache = YES;
return(samptr);
}
sample_was_in_cache = NO;
#ifdef DEBUG
printf("didn't find it\n");
#endif
sprintf(fnamebuf,"%s%s",SamplePath,fname);
#ifdef DEBUG
printf("looking for IFF file, name of %s\n",fnamebuf);
fflush(stdout);
#endif
if ((iffile = OpenIFF(fnamebuf, ID_8SVX)) < 0)
{
fprintf(stderr,"Load8SVX: can't open IFF sample file %s\n",fnamebuf);
return((Sample *)NULL);
}
if ((headsize = chunkuntil(iffile,ID_VHDR)) == -1)
{
fputs("Load8SVX: IFF 8SVX VHDR chunk search failed\n",stderr);
return((Sample *)NULL);
}
if (!readchunk(iffile,&voicehead,headsize))
{
fputs("Load8SVX: read of IFF VHDR chunk failed\n",stderr);
return((Sample *)NULL);
}
#ifdef DEBUG
DumpVoiceHead(&voicehead);
#endif
if ((samplebytes = chunkuntil(iffile,ID_BODY)) < 0)
{
fputs("Load8SVX: IFF 8SVX BODY chunk search failed\n",stderr);
return((Sample *)NULL);
}
if (voicehead.sCompression == sCmpFibDelta)
{
#ifdef DEBUG
fprintf(stderr,"Load8SVX: sample uses Fibonacci Delta Encoding\n");
#endif
fibbytes = samplebytes;
samplebytes = (fibbytes - 2) * 2;
}
if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_FAST)) == (char *)NULL)
{
if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_CHIP)) == (char *)NULL)
{
fputs("Load8SVX: unable to allocate memory for waveform\n",stderr);
return((Sample *)NULL);
}
else
flags = SAMPLE_ALLOCATED_IN_CHIP_RAM;
}
else
flags = SAMPLE_ALLOCATED_IN_FAST_RAM;
if (voicehead.sCompression == sCmpFibDelta)
{
/* load the delta compressed data into the back half of the sample
* buffer just allocated. We will decompress the data into the
* same sample memory, without overwriting the compressed data.
* It'll work. Trust me, I know what I'm doing.
*/
fibbufp = &sampbufp[samplebytes / 2];
if (!readchunk(iffile,fibbufp,fibbytes))
{
fputs("Read of fib sample data failed!\n",stderr);
FreeMem(sampbufp,samplebytes);
return((Sample *)NULL);
}
FibUnpack(fibbufp+2,fibbytes-2,sampbufp,fibbufp[1]);
}
else if (!readchunk(iffile,sampbufp,samplebytes))
{
fputs("Read of sample data failed!\n",stderr);
FreeMem(sampbufp,samplebytes);
return((Sample *)NULL);
}
close(iffile);
if ((samptr = (Sample *)AllocMem(sizeof(Sample),0L)) == (Sample *)NULL)
{
fputs("Load8SVX: unable to allocate memory for Sample structure\n",stderr);
FreeMem(sampbufp,samplebytes);
return((Sample *)NULL);
}
/* allocate memory for sample name */
if ((samptr->node.ln_Name = (char *)AllocMem(strlen(fname) + 1,0)) == (char *)NULL)
{
fputs("Load8SVX: unable to allocate memory for Sample name\n",stderr);
FreeMem(sampbufp,samplebytes);
FreeMem(samptr,sizeof(Sample));
return((Sample *)NULL);
}
/* structure copy in Voice8Header info */
samptr->sampleheader = voicehead;
/* set up pointer to sample data and store length */
if (flags & SAMPLE_ALLOCATED_IN_FAST_RAM)
{
samptr->fastsampledata = sampbufp;
samptr->sampledata = NULL;
}
else if (flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
{
samptr->fastsampledata = NULL;
samptr->sampledata = sampbufp;
}
samptr->samplebytes = samplebytes;
/* copy in the voice name */
strcpy(samptr->node.ln_Name,fname);
/* ...and set up the flags */
samptr->sample_flags = flags;
/* set the number of current "users" of the sample in chip RAM to zero */
samptr->chip_use_count = 0;
/* initialize the rest of the node fields */
samptr->node.ln_Type = samptr->node.ln_Pri = 0;
/* stick this new sample onto the end of the sample list */
AddTail(SampleList,&samptr->node);
#ifndef NOAUDIT
samptr->magic = SAMPLE_MAGIC;
#endif
#ifdef DEBUG
fprintf(stderr,"Load8SVX: waveform bytes %ld, samples/second %d\n",samplebytes,voicehead.samplesPerSec);
fprintf(stderr,"Load8SVX: samptr %lx, sampledata %lx\n",samptr,sampbufp);
#endif
return(samptr);
}
/* FibUnpack - unpack Fibonacci Delta Compressed audio sample
* see IFF file formats in the ROM Kernel Exec manual
* or on one of the Fred Fish disks
*/
char FibToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
FibUnpack(inp,n,outp,val)
char *inp, *outp;
long n;
char val;
{
register char pair;
#ifdef DEBUG
fprintf(stderr,"FibUnpack: inp %lx, n %ld, outp %lx, val %d\n",inp,n,outp,val);
#endif
while (n--)
{
pair = *inp++; /* get a pair of compressed samples */
val += FibToDelta[(pair >> 4) & 0xf]; /* uncompress first sample */
*outp++ = val;
val += FibToDelta[pair & 0xf]; /* uncompress second sample */
*outp++ = val;
}
}
/* unload sample at address */
UnloadSampleAt(samptr)
Sample *samptr;
{
ASSERT_SAMPLE_MAGIC(samptr);
#ifdef DEBUG
printf("UnloadSampleAt: Unloading Sample %s\n",samptr->node.ln_Name);
#endif
/* remove the sample from the sample list */
Remove(&samptr->node);
/* free the space allocated for the sample's name */
FreeMem(samptr->node.ln_Name,strlen(samptr->node.ln_Name)+1);
/* free the sample data itself */
if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
{
FreeMem(samptr->sampledata,samptr->samplebytes);
}
else
{
assert(samptr->sample_flags & SAMPLE_ALLOCATED_IN_FAST_RAM);
FreeMem(samptr->fastsampledata,samptr->samplebytes);
}
#ifndef NOAUDIT
samptr->magic = 0;
#endif
samptr->sample_flags = 0;
/* free the sample structure */
FreeMem(samptr,sizeof(Sample));
}
UnloadSample(name)
char *name;
{
Sample *samptr;
#ifdef DEBUG
printf("UnloadSample(%s)\n",name);
#endif
if ((samptr = (Sample *)FindName(SampleList,name)) != NULL)
UnloadSampleAt(samptr);
else
fprintf(stderr,"couldn't find sample %s to unload it\n",name);
}
#ifdef DEBUG
DumpVoiceHead(vptr)
Voice8Header *vptr;
{
printf("oneShotHiSamples %d, repeatHiSamples %d\n",
vptr->oneShotHiSamples, vptr->repeatHiSamples);
printf("samplesPerHiCycle %ld, samplesPerSec %d\n",
vptr->samplesPerHiCycle, vptr->samplesPerSec);
printf("ctOctave %d, sCompression %d, volume %d\n",
vptr->ctOctave, vptr->sCompression, vptr->volume);
}
#endif
/* end of 8svx.c */